#include "widget.h"
#include "ui_widget.h"
#include <functional>
#include <QDebug>


#define CHECK(B) \
    if(!(B)) return

#define CHECKR(B, A) \
    if(!(B)) return A

#define BIND_ON(s, e, f) \
    s->on(e, f) \


#define EMIT_MSG(s, e, d) \
    s->emit(e, d) \

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    m_io(new sio::client()),
    m_connectStatus(CLOSED),
    m_currentChannel("apple")
{
    ui->setupUi(this);
    m_channels["apple"] = m_io->socket("apple");
    m_channels["orange"] = m_io->socket("orange");
    m_channels["banana"] = m_io->socket("banana");

    using std::placeholders::_1;
    using std::placeholders::_2;
    using std::placeholders::_3;
    using std::placeholders::_4;

    for (auto ite = m_channels.begin(); ite != m_channels.end(); ++ite) {
        BIND_ON(ite->second, "message", std::bind(&Widget::onMessage, this, _1, _2, _3, _4));
    }

    m_io->set_socket_open_listener(std::bind(&Widget::onConnected,this,std::placeholders::_1));
    m_io->set_close_listener(std::bind(&Widget::onClosed,this,_1));
    m_io->set_fail_listener(std::bind(&Widget::onFailed,this));

    connect(ui->pushButton, &QPushButton::clicked, this, &Widget::onSendMessage);
    connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::onConnectServer);
    connect(ui->comboBox, &QComboBox::currentTextChanged, this, &Widget::onChannelChange);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::onConnected(const std::string &nsp)
{
    qDebug() << nsp.c_str();

}

void Widget::onClosed(const sio::client::close_reason &reason)
{
    qDebug() << reason;
}

void Widget::onFailed()
{
    qDebug() << "failed";
}

void Widget::onMessage(const std::string &name, const sio::message::ptr &data, bool hasAck, sio::message::list &ack_resp)
{

    qDebug() << name.c_str();
    Q_UNUSED(hasAck);
    Q_UNUSED(ack_resp);
    if(data->get_flag() == sio::message::flag_object)
    {
        const std::string& msg = data->get_map()["message"]->get_string();
        const std::string& robotname = data->get_map()["robotname"]->get_string();
        ui->textEdit->append((robotname + " say " + msg).c_str());
    }

}

void Widget::onSendMessage()
{
    CHECK(m_connectStatus != CLOSED);
    QString msg = ui->lineEdit->text();
    if (!msg.isEmpty()) {
        auto channel = m_channels[m_currentChannel];
//        channel->emit("message", std::string(msg.toLatin1().data()));
        EMIT_MSG(channel, "message", std::string(msg.toLatin1().data()));
    }

}

const char* server_url = "ws://localhost:3000";

void Widget::onConnectServer()
{
    CHECK(m_connectStatus != OPENED);
    m_io->connect(server_url);
    m_connectStatus = OPENED;

}

void Widget::onChannelChange(const QString &val)
{
    qDebug() << val;
    m_currentChannel = val;
}
